package com.qdxht.dispenser.utils;

import android.content.Context;
import android.graphics.*;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.HashMap;
import java.util.Map;

public final class RoundedQRCode {

    public static Bitmap create(Context context,
                                String content,
                                int side,
                                @Nullable Bitmap logo,
                                @ColorInt int colorDark){
        Bitmap bitmap = null;
        try {
            bitmap = create(context,
                    content,
                    side,
                    colorDark,   // 前景
                    Color.WHITE, // 背景
                    logo,
                    0.25f,       // Logo 占比
                    -1);
        } catch (WriterException e) {
            throw new RuntimeException(e);
        }
        return bitmap;
    }
    /**
     * 生成完全居中的圆角定位图案二维码
     *
     * @param ctx        Context
     * @param content    编码内容
     * @param outputSize 输出正方形边长(px)
     * @param darkColor  前景色
     * @param lightColor 背景色
     * @param logo       Logo；null 则无
     * @param logoRatio  Logo 占二维码比例 0~1
     * @param logoRadiusDp Logo圆角(0=直角，>0=圆角，-1=圆形)
     */
    public static Bitmap create(Context ctx,
                                String content,
                                int outputSize,
                                @ColorInt int darkColor,
                                @ColorInt int lightColor,
                                @Nullable Bitmap logo,
                                float logoRatio,
                                int logoRadiusDp) throws WriterException {

        /* 1. BitMatrix */
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.MARGIN, 0);
        var matrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, 0, 0, hints);
        int w = matrix.getWidth();
        int block = outputSize / w;
        // 除数转为int有误差，所以重新处理
        outputSize = block * w;

        /* 2. 画布居中留白 */
        int pad = dp2px(ctx, 0);               // 四周留白
        int canvasSize = outputSize + pad * 2;   // 输出总尺寸
        Bitmap bmp = Bitmap.createBitmap(canvasSize, canvasSize, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);
        c.drawColor(lightColor);

        /* 3. 二维码起点(居中) */
        int qrLeft = pad;
        int qrTop  = pad;

        Paint dark = new Paint(Paint.ANTI_ALIAS_FLAG);
        dark.setColor(darkColor);

        /* 4. 普通码点 */
        for (int y = 0; y < w; y++) {
            for (int x = 0; x < w; x++) {
                if (isFinder(x, y, w)) continue;
                if (matrix.get(x, y)) {
                    c.drawRect(qrLeft + x * block, qrTop + y * block,
                            qrLeft + (x + 1) * block, qrTop + (y + 1) * block, dark);
                }
            }
        }

        /* 5. 圆角定位图案 */
        float corner = block * 2.5f;
        drawFinder(c, 0, 0,        block, corner, dark, lightColor, qrLeft, qrTop);
        drawFinder(c, w - 7, 0,    block, corner, dark, lightColor, qrLeft, qrTop);
        drawFinder(c, 0, w - 7,    block, corner, dark, lightColor, qrLeft, qrTop);

        /* 6. Logo */
        if (logo != null) {
            int logoSize = (int) (outputSize * logoRatio);
            logo = scaleCenterCrop(logo, logoSize, logoSize);
            
            // 先绘制阴影
            int left = qrLeft + (outputSize - logoSize) / 2;
            int top  = qrTop  + (outputSize - logoSize) / 2;

            // 创建一个临时画布用于绘制阴影和Logo
            Bitmap tempBitmap = Bitmap.createBitmap(canvasSize, canvasSize, Bitmap.Config.ARGB_8888);
            Canvas tempCanvas = new Canvas(tempBitmap);
            
            // 设置阴影参数
            float shadowRadius = dp2px(ctx, 3f);
            float shadowDx = dp2px(ctx, 0.5f);
            float shadowDy = dp2px(ctx, 1.5f);
            int shadowColor = Color.parseColor("#66000000"); // 半透明黑色阴影
            
            Paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            shadowPaint.setColor(Color.WHITE);
            shadowPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
            
            // 根据Logo形状绘制阴影
            if (logoRadiusDp == -1) {
                // 圆形Logo
                float radius = logoSize / 2f;
                tempCanvas.drawCircle(left + radius, top + radius, radius, shadowPaint);
                
                // 绘制Logo
                logo = makeCircle(logo);
                tempCanvas.drawBitmap(logo, left, top, null);
            } else if (logoRadiusDp > 0) {
                // 圆角矩形Logo
                int cornerRadius = dp2px(ctx, logoRadiusDp);
                RectF rectF = new RectF(left, top, left + logoSize, top + logoSize);
                tempCanvas.drawRoundRect(rectF, cornerRadius, cornerRadius, shadowPaint);
                
                // 绘制Logo
                logo = makeRoundCorner(logo, cornerRadius);
                tempCanvas.drawBitmap(logo, left, top, null);
            } else {
                // 矩形Logo
                RectF rectF = new RectF(left, top, left + logoSize, top + logoSize);
                tempCanvas.drawRect(rectF, shadowPaint);
                
                // 绘制Logo
                tempCanvas.drawBitmap(logo, left, top, null);
            }
            
            // 将临时画布内容绘制到主画布
            c.drawBitmap(tempBitmap, 0, 0, null);
        }
        return bmp;
    }

    /* ======== 私有工具 ======== */
    
    private static boolean isFinder(int x, int y, int w) {
        int s = 7;
        return (x < s && y < s) || (x >= w - s && y < s) || (x < s && y >= w - s);
    }

    private static void drawFinder(Canvas c, int sx, int sy, int block, float r,
                                   Paint dark, int light, int offX, int offY) {
        int l = offX + sx * block, t = offY + sy * block, s = 7 * block;
        c.drawRoundRect(l, t, l + s, t + s, r, r, dark);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(light);
        p.setStyle(Paint.Style.FILL);
        int in = block;
        c.drawRoundRect(l + in, t + in, l + s - in, t + s - in, r * 0.7f, r * 0.7f, p);
        int in2 = 2 * block;
        c.drawRoundRect(l + in2, t + in2, l + s - in2, t + s - in2, r * 0.4f, r * 0.4f, dark);
    }

    private static Bitmap scaleCenterCrop(Bitmap src, int w, int h) {
        float scale = Math.max((float) w / src.getWidth(), (float) h / src.getHeight());
        Matrix m = new Matrix(); m.setScale(scale, scale);
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        new Canvas(bmp).drawBitmap(src, m, null);
        return bmp;
    }

    private static Bitmap makeRoundCorner(Bitmap src, int radiusPx) {
        Bitmap bmp = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        RectF rect = new RectF(0, 0, src.getWidth(), src.getHeight());
        c.drawRoundRect(rect, radiusPx, radiusPx, p);
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        c.drawBitmap(src, null, rect, p);
        return bmp;
    }

    private static Bitmap makeCircle(Bitmap src) {
        int s = Math.min(src.getWidth(), src.getHeight());
        Bitmap bmp = Bitmap.createBitmap(s, s, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        c.drawCircle(s / 2f, s / 2f, s / 2f, p);
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        c.drawBitmap(scaleCenterCrop(src, s, s), 0, 0, p);
        return bmp;
    }

    private static int dp2px(Context ctx, float dp) {
        return (int) (dp * ctx.getResources().getDisplayMetrics().density + 0.5f);
    }
}